from math import hypot

"""
特殊方法的存在是为了被Python解释器调用的，程序员自身并不需要调用它们
在执行len(my_object)时：
    如果my_object是一个自定义类的对象，Python会自己去调用由程序员实现的__len__方法
    如果my_object是Python内置类型，如list、str，那么CPython会抄个近路，__len__ 实际上会直接返回 PyVarObject 里的 ob_size 属性
    PyVarObject 是表示内存中长度可变的内置对象的 C 语言结构体。直接读取这个值比调用一个方法要快很多
"""


# 实现二维向量的特殊方法
class Vector:

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Vector(%r, %r)' % (self.x, self.y)

    def __abs__(self):
        return hypot(self.x, self.y)

    def __bool__(self):
        return bool(abs(self))

    # 向量加法运算
    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)

    # 向量乘法运算
    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

    # 布尔值
    def __bool__(self):
        # bool(x) 的背后是调用 x.__bool__() 的结果；如果不存 在 __bool__ 方法，那么 bool(x) 会尝试调用 x.__len__()。
        # 若返回 0，则 bool 会返回 False；否则返回 True
        return bool(self.x or self.y)


vector = Vector(1, 2)
print(vector)
print(bool(vector))

'''
跟运算符无关的特殊方法:
        类别                              方法名
字符串 / 字节序列表示形式      __repr__、__str__、__format__、__bytes__
数值转换                     __abs__、__bool__、__complex__、__int__、__float__、__hash__、__index__
集合模拟                     __len__、__getitem__、__setitem__、__delitem__、__contains__
迭代枚举                     __iter__、__reversed__、__next__
可调用模拟                   __call__
上下文管理                   __enter__、__exit__
实例创建和销毁                __new__、__init__、__del__
属性管理                     __getattr__、__getattribute__、__setattr__、__delattr__、__dir__
属性描述符                   __get__、__set__、__delete__
跟类相关的服务                __prepare__、__instancecheck__、__subclasscheck__
'''
'''
跟运算符相关的特殊方法:
        类别                              方法名
一元运算符                   __neg__ -、__pos__ +、__abs__ abs()
众多比较运算符                __lt__ <、__le__ <=、__eq__ ==、__ne__ !=、__gt__ >、__ge__ >=               
算术运算符                   __add__ +、__sub__ -、__mul__ *、__truediv__ /、__floordiv__ //、__mod__ %、
                            __divmod__divmod()、__pow__ ** 或pow()、__round__ round()
反向算术运算符                __radd__、__rsub__、__rmul__、__rtruediv__、__rfloordiv__、__rmod__、__rdivmod__、__rpow__
增量赋值算术运算符            __iadd__、__isub__、__imul__、__itruediv__、__ifloordiv__、__imod__、__ipow__
位运算符                     __invert__ ~、__lshift__ <<、__rshift__ >>、__and__ &、__or__ |、__xor__ ^
反向位运算符                 __rlshift__、__rrshift__、__rand__、__rxor__、__ror__
增量赋值位运算符              __ilshift__、__irshift__、__iand__、__ixor__、__ior__
'''